-- UIEngineeringManual
-- Create by dengc
-- 工程学手册

require "game/ui/form/dungeon/special/UIManualLearn"

-- UIEngineeringManual继承自Layer
UIEngineeringManual = class("UIEngineeringManual", function()
    return cc.Layer:create();
end);

function UIEngineeringManual.create()
    return UIEngineeringManual.new();
end

-- 地牢编号
local AVALON_ID = 1004;  -- 阿瓦隆要塞
local STEAM_ID  = 1003;  -- 蒸汽之都

-- 页面类型
local PAGE_TYPE_AVALON = "avalon";   -- 阿瓦隆手册
local PAGE_TYPE_STEAM  = "steam";    -- 蒸汽之都手册

-- 分页的数量
local TAB_NUM = 3;

-- 分页标签
local TAB_TYPE_BLASTING   = 1; -- 爆破学
local TAB_TYPE_CHEMISTRY  = 2; -- 化学
local TAB_TYPE_METALLURGY = 3; -- 冶金学
local TAB_TYPE_MACHINERY  = 4; -- 机械学
local TAB_TYPE_ELECTRIC   = 5; -- 电气学
local TAB_TYPE_AVIATION   = 6; -- 航空学

-- 格子相关
local ITEM_NAME = "item"; -- 格子前缀名
local MAX_LINE = 6;       -- 最大行
local MAX_ROW  = 6;       -- 最大列

-- 标签页的顺序
local TAB_ORDER = {
    [PAGE_TYPE_AVALON] = {TAB_TYPE_BLASTING,  TAB_TYPE_CHEMISTRY, TAB_TYPE_METALLURGY},
    [PAGE_TYPE_STEAM]  = {TAB_TYPE_MACHINERY, TAB_TYPE_ELECTRIC,  TAB_TYPE_AVIATION},
};

-- 类型与描述的映射
local typeIndexMap = {"blasting", "chemistry", "metallurgy", "machinery", "electric", "aviation"};

-- 构造函数
function UIEngineeringManual:ctor()
    -- 初始化
    self:setName("UIEngineeringManual");
    local node = cc.CSLoader:createNode("layout/dungeon/special/EngineeringManual.csb");
    self:addChild(node);
    self.node = node;

    local CT = node:getChildByName("CT");
    local BT = node:getChildByName("BT");

    self.CT = CT;
    self.BT = BT;

    self.selectIndex = 0;
    self.gridPanel = findChildByName(self.CT, "grid_panel");
    self:setLocalZOrder(UIMgr.TOP_MENU_ZORDER + 2)

    -- 注册点击事件
    self:registerTouchEvent();

    -- 初始化手册数据
    self:initData();

    -- 重绘标签页
    self:redrawTabs();

    -- 重绘格子
    self:redrawGrids();

    -- 重绘页面
    self:redraw();

    -- 注册事件回调
    self:registerEventCallback();

    -- 适配
    self:resize();
end

-- 注册事件回调
function UIEngineeringManual:registerEventCallback()
    EventMgr.removeAll("UIEngineeringManual");

    -- 注册学习工程学手册成功的回调
    EventMgr.register("UIEngineeringManual", event.LEARN_MANUAL_SUCCEED, function(para)
        local id = para["id"];

        -- 重新拉取数据
        self:initData(self.tabType);

        -- 重绘格子
        self:redrawGrids();

        -- 更新顶部菜单
        local uiTopMenu = UIMgr:getCurrentScene().topMenu;
        uiTopMenu:updateManualNeeds();

        -- 虚影效果
        self:playShadowEffect(id);
    end);

    -- 获得焦点的回调
    EventMgr.register("UIEngineeringManual", event.FOCUS_CHANGED, function(para)
        if para["get"] == "UIEngineeringManual" then
            if UIDungeonMgr:getCurLevel() then
                UIDungeonMgr:getCurLevel():hideMenu();
            end
        elseif para["lose"] == "UIEngineeringManual" then

        end
    end);

    -- 界面析构后，需要清理下
    self:registerScriptHandler(function(ev)
        local uiEquips = UIMgr:getCurrentScene():getFormByName("UIEquips");
        local uiTopMenu = UIMgr:getCurrentScene().topMenu;

        if ev == "exit" then
            -- 清除注册的事件
            EventMgr.removeAll("UIEngineeringManual");

            -- 显示装备界面
            if uiEquips then
                uiEquips:setVisible(true)
                uiEquips:show();
            end

            -- 隐藏顶部菜单
            uiTopMenu:setVisible(false);

            -- 还原顶部菜单的层级
            uiTopMenu:setLocalZOrder(self.oldZOrder);
        elseif ev == "enter" then
            -- 显示顶部菜单
            uiTopMenu:setVisible(true);
            uiTopMenu:show(TOPMENU_FRAME_MONEY, TOPMENU_FRAME_ENGINEERING_MANUAL, nil, true);
            self.oldZOrder = uiTopMenu:getLocalZOrder();
            uiTopMenu:setLocalZOrder(UIMgr.TOP_MENU_ZORDER + 3);

            -- 隐藏装备界面
            if uiEquips then uiEquips:setVisible(false) end
        end
    end);
end

-- 初始化数据
function UIEngineeringManual:initData(tabType)
    -- 根据地牢类型初始化页面类型
    local dungeonId = DungeonM.getDungeonId();

    -- 如果是子区域
    if DungeonAreaM.query(dungeonId, "type") == "child" then
        dungeonId = DungeonAreaM.getParentId(dungeonId);
    end

    self.pageType = (dungeonId == AVALON_ID) and PAGE_TYPE_AVALON or PAGE_TYPE_STEAM;

    -- 初始化分页类型
    if tabType then
        self.tabType = tabType;
    elseif self.pageType == PAGE_TYPE_AVALON then
        self.tabType = TAB_TYPE_BLASTING;
    else
        self.tabType = TAB_TYPE_MACHINERY;
    end

    -- 根据类型初始化手册数据
    self.typeData = table.deepcopy(EngineeringManualM.querySubject(self.tabType));

    -- 设置学习情况
    self:setData();
end

-- 设置学习情况
function UIEngineeringManual:setData()
    local manualInfo = ME.user.dbase:query("engineering_manual") or {};
    for id, data in pairs(self.typeData) do
        self.typeData[id]["level"] = EngineeringManualM.getKnowledgeLevel(data.id);
    end
end

-- 注册标签页点击回调
function UIEngineeringManual:registerTabTouchEvent(node)
    -- 节点
    local tabImage = node:getChildByName("tab");
    local tabLight = node:getChildByName("light");
    local tabIcon = node:getChildByName("icon");
    local tabNode = findChildByName(self.node, "CT/tab");

    -- 置灰颜色
    local blendColor = TextStyleM.TEXT_COLOR_BLEND;
    local normalColor = TextStyleM.TEXT_COLOR_NORMAL;

    local function onClick(sender, eventType)
        -- 点击时的回调
        if eventType == ccui.TouchEventType.ended then
            AudioM.playFx("button_click");

            -- 设置当前的分页类型
            self.tabType = node.type;

            -- 根据类型初始化手册数据
            self.typeData = table.deepcopy(EngineeringManualM.querySubject(self.tabType));

            -- 设置学习情况
            self:setData();

            -- 去除其它高亮
            for i = 1, #tabNode.rows do
                tabNode.rows[i]:getChildByName("light"):setVisible(false);
                tabNode.rows[i]:getChildByName("tab"):setColor(blendColor);
                tabNode.rows[i]:getChildByName("icon"):setColor(blendColor);
            end

            -- 设置本身高亮
            tabLight:setVisible(true);
            tabImage:setColor(normalColor);
            tabIcon:setColor(normalColor);

            -- 重绘
            self.selectIndex = 0;
            self:redrawGrids();
            self:redraw();
        end
    end

    tabImage:addTouchEventListener(onClick);
end

-- 注册点击事件
function UIEngineeringManual:registerTouchEvent()
    local node = self.node;

    -- 注册返回按钮点击事件
    local btnBack = findChildByName(self.BT, "btn_back");
    local function onBackClick(sender, eventType)
        if eventType == ccui.TouchEventType.ended then
            -- 关闭当前界面
            AudioM.playFx("button_return");
            UIMgr.getCurrentScene():removeFormByName("UIEngineeringManual");
        end
    end
    AddBackEventHandler(self, btnBack, onBackClick);
    TextStyleM.setTextStyle(btnBack, TextStyleM.TEXT_SIZE_MIDDLE, TextStyleM.TEXT_COLOR_BROWN_YELLOW, true);
    btnBack:setTitleText(getLocStr("btn_text_back"));
end

-- 绘制标签页
function UIEngineeringManual:redrawTabs()
    local tabNode = findChildByName(self.node, "CT/tab");

    -- 标签页数量
    local tabNum = TAB_NUM;

    -- 先移除旧的标签
    tabNode.rows = {};
    tabNode:removeAllChildren();

    -- 根据tab数据，生成新标签
    local widget = replaceNodeWithWidget(cc.CSLoader:createNode("layout/tab/tab.csb"));

    -- 置灰颜色
    local blendColor = TextStyleM.TEXT_COLOR_BLEND;
    local normalColor = TextStyleM.TEXT_COLOR_NORMAL;

    for i = 1, tabNum do
        local child = widget:clone();
        child:setName("tab" .. i);
        child.type = TAB_ORDER[self.pageType][i];

        self:registerTabTouchEvent(child);

        -- 计算单元格坐标
        -- 这个坐标将是单元格的描点所在
        local x = (i - 1) * 95 + 67;
        local y = 75;

        child:setPositionX(x);
        child:setPositionY(y);

        local tabLight = findChildByName(child, "light");
        local tabImage = findChildByName(child, "tab");
        tabLight:setScaleY(1.5);
        tabImage:setScaleY(1.5);

        local tabText = findChildByName(child, "text");
        local tabIcon = findChildByName(child, "icon");

        tabText:setVisible(true);
        tabIcon:setVisible(false);

        local tabType = TAB_ORDER[self.pageType][i];
        if tabType == self.tabType then
            tabLight:setVisible(true);
            tabImage:setColor(normalColor);
        else
            tabLight:setVisible(false);
            tabImage:setColor(blendColor);
        end

        local kerning = -4;
        if not isFullWidthLang() then
            kerning = -3;
        end
        local tabStr = getLocStr("engineering_manual_title_" .. tabType);
        TextStyleM.setOutlineStyle(tabText, TextStyleM.TEXT_OUTLINE_SIZE, TextStyleM.TEXT_OUTLINE_COLOR_DARK);
        TextStyleM.setTextStyle(tabText, TextStyleM.TEXT_SIZE_SMALL2, TextStyleM.TEXT_COLOR_BROWN_YELLOW, true, kerning, nil, nil, nil, nil, nil, TextStyleM.getTextScale(tabStr, 6));
        tabText:setString(tabStr);

        tabNode:addChild(child)
        table.insert(tabNode.rows, child)
    end

    for i = 1, #tabNode.rows do
        local tab = tabNode.rows[i];
        tab:setPositionY(tab:getPositionY() + 100);
    end

    performWithDelay(self, function() self:playTabEffect(); end, 0.2);
end

-- 页签动画效果
function UIEngineeringManual:playTabEffect()
    local tabNode = findChildByName(self.node, "CT/tab");
    -- 带窗口动画播放结束后，页签从上面往下掉
    for i = 1, #tabNode.rows do
        local tab = tabNode.rows[i];
        local pos = cc.p(tab:getPosition());
        local delay = cc.DelayTime:create(0.15 * (i - 1));
        local moveDown = cc.MoveTo:create(0.15, cc.p(pos.x, pos.y - 100 - 5));
        local moveBack = cc.MoveTo:create(0.15, cc.p(pos.x, pos.y - 100));
        local action = cc.Sequence:create(delay, moveDown, moveBack);
        tab:runAction(action);
    end
end

-- 重绘页面
function UIEngineeringManual:redraw()
    local typeData = self.typeData;
    local tabType  = self.tabType;

    -- 标题
    local titleLabel = findChildByName(self.CT, "title_label");
    local titleStr = getLocStr("engineering_manual_title_" .. tabType);
    titleLabel:getVirtualRenderer():setHorizontalAlignment(cc.TEXT_ALIGNMENT_CENTER);
    TextStyleM.setTextStyle(titleLabel, 34, TextStyleM.TEXT_COLOR_ORANGE, true, -2, nil, nil, nil, TextStyleM.TEXT_SIZE_MIDDLE2, true, 1);
    TextStyleM.setShadowStyle(titleLabel, cc.size(0, -3));
    TextStyleM.setOutlineStyle(titleLabel, 1.5, TextStyleM.TEXT_OUTLINE_COLOR, true);
    titleLabel:setString(titleStr);

    -- 线路图
    local diagramNode = findChildByName(self.CT, "diagram");
    local bgNode = cc.CSLoader:createNode("layout/dungeon/special/manual_bg_" .. self.tabType .. ".csb");
    diagramNode:removeAllChildren();
    diagramNode:addChild(bgNode);
    bgNode:setPosition(-322, -486.00);
    bgNode:setScaleX(0.94);
    bgNode:setScaleY(1.01);
end

-- 重绘容器
function UIEngineeringManual:redrawGrids()
    local typeData = self.typeData;
    self.gridPanel:removeAllChildren();

    local itemNode = cc.CSLoader:createNode("layout/dungeon/special/ManualItem.csb");
    local widget = replaceNodeWithWidget(itemNode);

    -- 图标间距(横向)
    local wGap = 5;

    -- 图标间距(纵向)
    local hGap = 0;

    -- 图标宽度
    local iconWidth = 76;

    -- 图片高度
    local iconHeight = 76;

    -- 距顶部长度
    local topHGap  = 10;

    -- 距左边界长度
    local leftWGap = 5;

    -- 距底部长度
    local bottomHGap = 20;

    for _, info in pairs(typeData) do
        local pos = EngineeringManualM.query(info.id, "pos");
        local posX = pos[1];
        local posY = pos[2];
        local id = info.id;

        local node = widget:clone();
        node:setName(ITEM_NAME .. id);
        node:setPosition((posX - 1) * (iconWidth + wGap) + leftWGap, self.gridPanel:getContentSize().height - topHGap - posY * (iconHeight + hGap) + hGap);

        -- 把一些数据记录在格子下面
        node.id = id;
        self.gridPanel:addChild(node);

        -- 绘制知识点
        self:initKnowledgeItem(node, info);
    end
end

-- 绘制知识点
function UIEngineeringManual:initKnowledgeItem(node, info)
    node:setScale(0.6);

    -- 如果不显示，隐藏
    if EngineeringManualM.needHideSubject(info["id"]) then
        node:setVisible(false);
        return;
    end

    -- 名称
    local nameLabel = findChildByName(node, "name_label");
    nameLabel:setVisible(false);

    -- icon
    local icon = findChildByName(node, "icon");
    icon:loadTexture(getItemIconPath(info.icon));
    icon:setScale(1.2)

    local offset = EngineeringManualM.query(info.id, "offset");
    icon:setPosition(icon:getPositionX() + offset[1] + 5, icon:getPositionY() + offset[2] + 7);

    -- 背景框
    local iconBg = findChildByName(node, "bg");
    local bgGray = findChildByName(node, "gray_bg");

    -- 等级标签
    local levelNode = findChildByName(node, "level");
    local lightStarPath = "images/ui/symbol/energy_little.png";
    local darkStarPath  = "images/ui/symbol/energy_little2.png";
    levelNode:setPosition(levelNode:getPositionX() - 4, levelNode:getPositionY() - 4);

    local focusBg = findChildByName(node, "focus");
    focusBg:setVisible(false);

    -- 根据条件画背景框
    local level = info["level"];
    local maxLevel = info["max_level"];
    if level > 0 then
        -- 激活已学习
        iconBg:setVisible(true);
        bgGray:setVisible(false);
        icon:setOpacity(255);
        local layer = createStarLayerEx(level, maxLevel, lightStarPath, darkStarPath, "center", -0.6);
        if layer then
            levelNode:removeAllChildren();
            levelNode:addChild(layer);
        end
    elseif level == 0 and EngineeringManualM.checkIsLearn(info.last_id) or 1 == EngineeringManualM.canIgnoreLast(info.id) then
        -- 激活未学习
        iconBg:setVisible(true);
        bgGray:setVisible(false);
        icon:setOpacity(170);
        local layer = createStarLayerEx(level, maxLevel, lightStarPath, darkStarPath, "center", -0.6);
        if layer then
            levelNode:removeAllChildren();
            levelNode:addChild(layer);
        end
    else
        -- 未激活
        iconBg:setVisible(false);
        bgGray:setVisible(true);
        setGrayMode(icon, true);
    end

    -- 注册点击事件
    self:registerItemTouchEvent(node);
end

-- 注册格子点击事件
function UIEngineeringManual:registerItemTouchEvent(node)
    local image = node:getChildByName("bg");
    local grayImage = node:getChildByName("gray_bg");

    local function onClick(sender, eventType)
        -- 点击时的回调
        if eventType == ccui.TouchEventType.ended then
            AudioM.playFx("button_click");

            local lastSelected = self.selectIndex;

            self.selectIndex = node.id;

            self:itemSelected(lastSelected, node.id);
        end
    end

    image:addTouchEventListener(onClick);
    grayImage:addTouchEventListener(onClick);
end

-- 格子选中效果
function UIEngineeringManual:itemSelected(lastSelected, nowSelected)
    -- 打开知识点学习界面
    AudioM.playFx("button_receive");

    local uiManualLearn = UIManualLearn.create(nowSelected);
    UIMgr.getCurrentScene():addForm(uiManualLearn);
end

-- 是否显示学习界面
function UIEngineeringManual:isShowManualLearn(id)
    -- 是可无限学习的知识点
    local lastId = EngineeringManualM.query(id, "last_id");

    -- 不需要判断父节点的
    if 1 == EngineeringManualM.canIgnoreLast(id) then
        return true;
    end

    if  not EngineeringManualM.checkIsLearn(lastId) and
        lastId ~= -1 then
        return false;
    end

    -- 本知识点已经学习
    if EngineeringManualM.checkIsLearn(id) then
        return true;
    end

    -- 上一个知识点还没有开启
    if not EngineeringManualM.checkIsLearn(lastId) then
        return false;
    end

    return true;
end

-- 学习知识点成功后的虚影效果
function UIEngineeringManual:playShadowEffect(id)
    local node = findChildByName(self.gridPanel, ITEM_NAME .. id);
    local iconPath = getItemIconPath(EngineeringManualM.query(id, "icon"));

    playNormalShadowEffect(node, iconPath);
end

-- 适配
function UIEngineeringManual:resize()
    local node = self.node;

    -- bg居中显示并充满整个屏幕
    AlignM.fitToScreen(node, "bg");

    -- CT居中并缩放至合适大小
    AlignM.alignToCenter(node, "CT");

    -- BT置于底部并缩放至合适大小
    AlignM.alignToBottomCenter(node, "BT");
end
